package com.demo.supplier.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.demo.supplier.config.JwtProperties;
import com.demo.supplier.dto.LoginDto;
import com.demo.supplier.dto.UserDto;
import com.demo.supplier.entity.SysUser;
import com.demo.supplier.exception.BusinessException;
import com.demo.supplier.mapper.SysUserMapper;
import com.demo.supplier.service.FileService;
import com.demo.supplier.service.SysUserService;
import com.demo.supplier.utils.CommonUtil;
import com.demo.supplier.utils.JwtUtil;
import com.demo.supplier.vo.LoginVo;
import com.demo.supplier.vo.UserDetailVo;
import com.demo.supplier.vo.UserVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 用户服务实现类
 * 
 * @author demo
 */
@Slf4j
@Service
public class SysUserServiceImpl implements SysUserService {

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private JwtUtil jwtUtil;

    @Autowired
    private JwtProperties jwtProperties;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private FileService fileService;

    private static final String REDIS_LOGIN_KEY = "user:login:";

    @Override
    public LoginVo login(LoginDto loginDto) {
        // 查询用户
        SysUser user = getUserByUsername(loginDto.getUsername());
        if (user == null) {
            throw new BusinessException("用户名或密码错误");
        }

        // 验证密码
        if (!CommonUtil.checkPassword(loginDto.getPassword(), user.getPassword())) {
            throw new BusinessException("用户名或密码错误");
        }

        // 检查用户状态
        if (user.getStatus() == null || user.getStatus() != 1) {
            throw new BusinessException("用户已被禁用");
        }

        // 生成JWT Token
        String token = jwtUtil.generateToken(user.getId(), user.getUsername());
        if (token == null) {
            throw new BusinessException("生成Token失败");
        }

        // 将用户信息存储到Redis
        String redisKey = REDIS_LOGIN_KEY + user.getId();
        UserVo userVo = BeanUtil.copyProperties(user, UserVo.class);
        redisTemplate.opsForValue().set(redisKey, userVo, jwtProperties.getExpire(), TimeUnit.SECONDS);

        // 构建返回结果
        LoginVo loginVo = new LoginVo();
        loginVo.setToken(token);
        loginVo.setUserInfo(userVo);
        loginVo.setExpireTime(jwtProperties.getExpire());

        return loginVo;
    }

    @Override
    public void logout() {
        Long userId = getCurrentUserId();
        if (userId != null) {
            String redisKey = REDIS_LOGIN_KEY + userId;
            redisTemplate.delete(redisKey);
        }
    }

    @Override
    public UserVo getCurrentUserInfo() {
        Long userId = getCurrentUserId();
        if (userId == null) {
            throw new BusinessException(401, "用户未登录");
        }

        String redisKey = REDIS_LOGIN_KEY + userId;
        UserVo userVo = (UserVo) redisTemplate.opsForValue().get(redisKey);
        if (userVo == null) {
            throw new BusinessException(401, "登录状态已过期");
        }

        return userVo;
    }

    @Override
    public Page<UserVo> pageUsers(int current, int size, String keyword) {
        Page<SysUser> page = new Page<>(current, size);
        
        LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();
        if (StrUtil.isNotBlank(keyword)) {
            wrapper.like(SysUser::getUsername, keyword)
                   .or()
                   .like(SysUser::getRealName, keyword)
                   .or()
                   .like(SysUser::getEmail, keyword);
        }
        wrapper.orderByDesc(SysUser::getCreateTime);

        Page<SysUser> userPage = sysUserMapper.selectPage(page, wrapper);
        
        // 转换为VO
        List<UserVo> userVos = userPage.getRecords().stream()
                .map(user -> BeanUtil.copyProperties(user, UserVo.class))
                .collect(Collectors.toList());

        Page<UserVo> result = new Page<>(current, size);
        result.setRecords(userVos);
        result.setTotal(userPage.getTotal());
        return result;
    }

    @Override
    public void createUser(UserDto userDto) {
        // 检查用户名是否存在
        if (getUserByUsername(userDto.getUsername()) != null) {
            throw new BusinessException("用户名已存在");
        }

        // 验证头像文件ID是否有效
        if (userDto.getAvatarFileId() != null) {
            validateFileId(userDto.getAvatarFileId());
        }

        SysUser user = BeanUtil.copyProperties(userDto, SysUser.class);
        
        // 密码加密
        if (StrUtil.isNotBlank(userDto.getPassword())) {
            user.setPassword(CommonUtil.encryptPassword(userDto.getPassword()));
        } else {
            throw new BusinessException("密码不能为空");
        }

        // 设置默认值
        if (user.getStatus() == null) {
            user.setStatus(1);
        }

        sysUserMapper.insert(user);
    }

    @Override
    public void updateUser(UserDto userDto) {
        if (userDto.getId() == null) {
            throw new BusinessException("用户ID不能为空");
        }

        SysUser existUser = sysUserMapper.selectById(userDto.getId());
        if (existUser == null) {
            throw new BusinessException("用户不存在");
        }

        // 检查用户名是否重复（排除自己）
        SysUser checkUser = getUserByUsername(userDto.getUsername());
        if (checkUser != null && !checkUser.getId().equals(userDto.getId())) {
            throw new BusinessException("用户名已存在");
        }

        // 验证头像文件ID是否有效
        if (userDto.getAvatarFileId() != null) {
            validateFileId(userDto.getAvatarFileId());
        }

        // 处理头像文件更改
        if (!Objects.equals(existUser.getAvatarFileId(), userDto.getAvatarFileId())) {
            if (existUser.getAvatarFileId() != null) {
                try {
                    fileService.deleteFileById(existUser.getAvatarFileId());
                } catch (Exception e) {
                    log.warn("删除旧头像文件失败", e);
                }
            }
        }

        SysUser user = BeanUtil.copyProperties(userDto, SysUser.class);
        
        // 如果有新密码，则加密
        if (StrUtil.isNotBlank(userDto.getPassword())) {
            user.setPassword(CommonUtil.encryptPassword(userDto.getPassword()));
        } else {
            user.setPassword(null); // 不更新密码
        }

        sysUserMapper.updateById(user);
    }

    @Override
    public void deleteUser(Long id) {
        SysUser user = sysUserMapper.selectById(id);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }

        sysUserMapper.deleteById(id);
    }

    @Override
    public SysUser getUserByUsername(String username) {
        LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysUser::getUsername, username);
        return sysUserMapper.selectOne(wrapper);
    }

    /**
     * 获取当前登录用户ID
     */
    private Long getCurrentUserId() {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attributes == null) {
            return null;
        }

        HttpServletRequest request = attributes.getRequest();
        String token = request.getHeader("Authorization");
        if (StrUtil.isBlank(token) || !token.startsWith("Bearer ")) {
            return null;
        }

        token = token.substring(7);
        return jwtUtil.getUserId(token);
    }

    @Override
    public UserDetailVo getUserWithAvatar(Long userId) {
        SysUser user = sysUserMapper.selectById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }

        UserDetailVo detailVo = BeanUtil.copyProperties(user, UserDetailVo.class);
        
        // 获取头像文件信息
        if (user.getAvatarFileId() != null) {
            try {
                detailVo.setAvatarFile(fileService.getFileInfo(user.getAvatarFileId()));
            } catch (Exception e) {
                log.warn("获取头像文件信息失败", e);
            }
        }
        
        return detailVo;
    }

    /**
     * 验证文件ID是否有效
     */
    private void validateFileId(Long fileId) {
        if (fileId != null) {
            try {
                fileService.getFileInfo(fileId);
            } catch (Exception e) {
                throw new BusinessException("文件ID " + fileId + " 不存在或已被删除");
            }
        }
    }
}